package com.test.auth_db_auto.support.code.picture;

import com.test.auth_db_auto.support.BootSecurityProperties;
import com.test.auth_db_auto.support.DefaultBeanName;
import com.test.auth_db_auto.support.code.BootCodeService;
import com.test.auth_db_auto.support.code.VerificationCode;
import com.test.auth_db_auto.support.code.VerificationCodeGeneration;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;

/**
 * @ Author: .Mr
 * @ ClassName DefaultPictureCodeGeneration
 * @ Description TODO
 * @ date 2021/12/25 16:38
 * @ Version 1.0
 * 图像验证码生成规则
 */
@Component(DefaultBeanName.DEFAULT_PICTURE_CODE_GENERATOR_BEAN)
public class DefaultPictureCodeGeneration implements VerificationCodeGeneration<BufferedImage,String> {

    private static final String SOURCE_CODES="123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";  //内容
    private static int height=40; //高
    private static int width=95;  //宽
    private static Random random=new Random();
    private BootSecurityProperties properties;
    private BootCodeService<String> codeService;

    public DefaultPictureCodeGeneration(BootSecurityProperties properties, BootCodeService<String> codeService) {
        this.properties = properties;
        this.codeService = codeService;
    }

    @Override
    public VerificationCode<BufferedImage> generator(String key) throws Exception {

        String code=createCodeStr(4);

        int verifySize=code.length();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Random random = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        Color[] colors = new Color[5];
        Color[] colorSpaces = {Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
                Color.ORANGE, Color.PINK, Color.YELLOW};
        float[] floats = new float[colors.length];
        for(int i=0;i<colors.length;i++){
            colors[i]=colorSpaces[random.nextInt(colorSpaces.length)];
            floats[i]=random.nextFloat();
        }
        Arrays.sort(floats);

        //设置边框颜色
        g2.setColor(Color.GRAY);
        g2.fillRect(0,0,width,height);

        Color c = getRandColor(200, 250);
        //设置背景色
        g2.setColor(c);
        g2.fillRect(0,2,width,height-4);

        //绘制干扰线
        //设置线条颜色
        g2.setColor(getRandColor(160,200));
        for(int i=0;i<20;i++){
            int x = random.nextInt(width - 1);
            int y = random.nextInt(height - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        //添加噪点
        //噪声率
        float ypRate=0.05f;
        int area=(int)(ypRate*width*height);
        for(int i=0;i<area;i++){
            int x=random.nextInt(width);
            int y=random.nextInt(height);
            int rgb=getRandomTntColor();
            image.setRGB(x,y,rgb);
        }

        g2.setColor(getRandColor(100,160));
        int fontSize=height-5;
        Font font=new Font("Algerian",Font.ITALIC,fontSize);
        g2.setFont(font);
        char[] chars=code.toCharArray();
        for(int i=0;i<verifySize;i++){
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * random.nextDouble() * (random.nextBoolean() ? 1 : -1), (width / verifySize) * i + fontSize / 2, height / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((width - 10) / verifySize) * i + 5, height / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        codeService.setCodeValue(key, code);
        return new VerificationCode<BufferedImage>(image,properties.getCodeExpireTime());
    }

    //获取对应的验证码内容
    private static String createCodeStr(int codeLength){
        Random random = new Random();
        StringBuffer builder = new StringBuffer();
        for(int i=0;i<codeLength;i++){
            int key=random.nextInt(SOURCE_CODES.length()-1);
            builder.append(SOURCE_CODES.charAt(key));
        }
        return builder.toString();
    }
    /**
     * 添加背景颜色
     * */
    private static int[] getRandomRgb(){
        int[] rgb=new int[3];
        for(int i=0;i<3;i++){
            rgb[i]=random.nextInt(255);
        }
        return rgb;
    }

    private static int getRandomTntColor(){
        int [] rgb=getRandomRgb();
        int color=0;
        for (int c : rgb ){
            color = color <<8;
            color = color | c;
        }
        return color;
    }

    private static Color getRandColor(int fc, int bc){

        Random random = new Random();

        if(fc>255){
            fc=255;
        }
        if(bc>255){
            bc=255;
        }

        int r=fc+random.nextInt(bc-fc);
        int g=fc+random.nextInt(bc-fc);
        int b=fc+random.nextInt(bc-fc);
        return new Color(r,g,b);
    }
}
